<template>
  <div class="flex-column topo-wrap h-100">
    <div
      class="flex justify-between map-top"
      :style="{
        width: fullScreen ? '100%' : `calc(100% - ${staticsItem.width * 2}px)`
      }"
    >
      <TopFilter
        v-show="!isEdit"
        ref="TopFilter"
        :map-type="mapType"
        @operateFullScreen="operateFullScreen"
        @regionChanged="regionChanged"
      />
      <!-- 右边刷新和保存按钮 -->
      <div class="flex flex-1 justify-end align-center">
        <gis-search v-if="mapType === 'GisView' && fullScreen" @locatePoint="locatePoint" />
        <template v-if="!rightVisiable && !isEdit">
          <el-button
            type="primary"
            class="topo-change-btn"
            :class="mapType === 'VisView' ? 'topo-deactive' : ''"
            style="margin-right: 10px"
            @click="changeMap"
          >
            {{ $t('TOPOLOGICAL_GRAPH') }}
          </el-button>
          <el-button type="primary" class="ml-10" @click="refreshTopo(true)">
            {{ $t('REFRESH') }}
          </el-button>
          <el-button
            v-if="permission.save && !operateType"
            type="primary"
            class="ml-10"
            @click="modMap"
          >
            {{ $t('EDIT') }}
          </el-button>
          <el-button
            v-show="fullScreen && mapType === 'GisView' && zoom > 12.8"
            type="primary"
            class="ml-10 topo-change-btn"
            :class="facilityVisiable ? 'topo-deactive' : ''"
            @click="$store.commit('showFacility', !facilityVisiable)"
          >{{ $t('FACILITY') }}</el-button>
          <LayingMethodFilter v-if="mapType === 'GisView'" />
        </template>
        <template v-if="isEdit">
          <el-button type="primary" class="ml-10" @click="cancelEdit(false)">
            {{ $t('CANCEL_EDIT') }}
          </el-button>
          <el-button
            v-show="mapType === 'VisView'"
            type="primary"
            class="ml-10"
            @click="autoLayout"
          >{{ $t('AUTO_LAYOUT') }}</el-button>
          <el-button type="primary" class="ml-10" @click="saveEdit">
            {{ $t('SAVE') }}
          </el-button>
        </template>
      </div>
    </div>
    <div v-loading="showLoading" class="w-100 h-100 flex">
      <component
        :is="mapType"
        id="mapContainer"
        ref="mapContainer"
        class="flex-1"
        :nodes="nodes"
        :edges="edges"
        :operate-type="operateType"
        :statics-item="staticsItem"
        :is-edit="isEdit"
        :show-type="showType"
        :btn-in="btnIn"
        :full-screen="fullScreen"
        :preview-statisics-name="previewStatisicsName"
        :selected-all="selectedAll"
        @zoomChange="zoomChange"
        @hoverEdge="hoverEdge"
        @selectEdge="selectEdge"
        @hoverNode="hoverNode"
        @selectNode="selectNode"
        @hoverCluster="hoverCluster"
        @hoverFacility="hoverFacility"
        @dragStart="dragStart"
        @refresh="refreshTopo"
        @disableEdit="isEdit = false"
      />
      <AddRight
        v-if="!isEdit"
        ref="addRight"
        @rightVisiableChange="rightVisiableChange"
        @mouseEvent="mouseEventChange"
        @restore="restoreFn"
        @reduction="reductionFn"
        @close="closeBiz"
        @refresh="getTopos"
      />
    </div>
    <!-- 点击节点、光缆事件弹窗 -->
    <el-card
      v-if="clickProp !== '' || (btnIn && !isEdit)"
      class="edges-tooltip mouseEventClick"
      :style="{ 'z-index': mouseEvent === 'deviceClick' ? 3000 : 9, ...clickPosition }"
      @mouseover.native="btnCardIn(true)"
      @mouseleave.native="btnCardIn(false)"
      @contextmenu.native.prevent
    >
      <!-- 关系线click时显示 -->
      <ul v-if="mouseEvent === 'fiberClick'">
        <li v-if="permission.cable">
          <el-button class="w-100" type="primary" @click="cableDetailClick">
            {{ $t('FIBER_DETAIL') }}
          </el-button>
        </li>
        <li v-if="permission.loss">
          <el-button class="w-100" type="primary" @click="lossClick">
            {{ $t('MENU_LOSS_THRESHOLD') }}
          </el-button>
        </li>
        <li
          v-if="
            currentEdge.cableSegmentIds &&
              currentEdge.cableSegmentIds.length &&
              permission.cableSegment
          "
        >
          <el-button class="w-100" type="primary" @click="cableSegmentClick('view')">
            {{ $t('CABLE_SEGMENT_DETAIL') }}
          </el-button>
        </li>
        <li>
          <el-button class="w-100" type="primary" @click="showAssociatedBiz('cable')">{{
            $t('ASSOCIATED_SERVICE')
          }}</el-button>
        </li>
        <li v-if="permission.segment">
          <el-button class="w-100" type="primary" @click="showAssociatedSegment(true)">
            {{ $t('ASSOCIATION_SEGMENT') }}
          </el-button>
        </li>
      </ul>
      <!-- 节点click时显示 -->
      <ul v-if="mouseEvent === 'stationClick'">
        <li v-if="permission.biz && bizNodeList.length">
          <el-button type="primary" @click="associatedBusinessClick('NODE')">
            {{ $t('ASSOCIATED_SERVICE') }}
          </el-button>
        </li>
        <li v-if="permission.faultBiz && bizNodeList.length && bizList.length">
          <el-button type="primary" @click="faultBusinessClick('NODE')">
            {{ $t('FAULT_SERVICE') }}
          </el-button>
        </li>
        <li v-if="permission.site">
          <el-button type="primary" @click="deviceClick">{{ $t('SITE_DETAIL') }}</el-button>
        </li>
        <li v-if="permission.open && bizNodeList.length">
          <el-button type="primary" @click="openClick">
            {{ $t('BUSINESS_TYPES_SMART_OPEN') }}
          </el-button>
        </li>
      </ul>
      <ul v-if="mouseEvent === 'stationRightClick' && permission.modstation">
        <li>
          <el-button type="primary" @click="editStation">{{ $t('MOD_STATION') }}</el-button>
        </li>
        <li>
          <el-button type="primary" @click="delStation">{{ $t('DEL_STATION') }}</el-button>
        </li>
      </ul>
      <ul v-if="mouseEvent === 'cableRightClick'">
        <li>
          <el-button type="primary" class="w-100" @click="editPath">
            {{ $t('EDIT_PATH') }}
          </el-button>
        </li>
        <li>
          <el-button type="primary" @click="cableSegmentClick('edit')">
            {{ $t('EDIT_FIBER_CABLE') }}
          </el-button>
        </li>
      </ul>
      <ul v-if="mouseEvent === 'mapRightClick' && permission.addstation">
        <li>
          <el-button type="primary" class="w-100" @click="addStation">
            {{ $t('ADD_STATION') }}
          </el-button>
        </li>
        <li v-if="zoom > 12.8">
          <el-button type="primary" @click="addFacility">
            {{ $t('ADDE_FACILITY') }}
          </el-button>
        </li>
      </ul>
      <ul v-if="mouseEvent === 'facilityClick'">
        <li>
          <el-button type="primary" class="w-100" @click="addFacility">
            {{ $t('EDIT_GEO_NODE') }}
          </el-button>
        </li>
        <li>
          <el-button type="primary" @click="delFacility">
            {{ $t('DEL_GEO_NODE') }}
          </el-button>
        </li>
      </ul>
      <ul v-if="mouseEvent === 'deviceClick'">
        <li>
          <el-button type="primary" @click="showPortDetail">{{ $t('PORT_DETAILS') }}</el-button>
        </li>
        <li>
          <el-button type="primary" @click="showAssociatedBiz('device')">{{
            $t('ASSOCIATED_SERVICE')
          }}</el-button>
        </li>
      </ul>
    </el-card>
    <CableTabs
      v-show="(mouseEvent === 'fiberHover' && !isEdit) || (infoBoxIn && !isEdit)"
      :cable-list="cableList"
      :cable="currentEdge"
      :map-type="mapType"
      class="edges-tooltip cableTabsDetail"
      :style="hoverPosition"
      @leave="cableTabLeave"
      @mouseover="infoBoxIn = true"
      @cableTabsHover="cableTabsHover"
      @clickTab="clickCableTab"
    />
    <station-detail
      v-show="mouseEvent === 'stationHover' || stationIn"
      class="absolute hoverstationDetail"
      :station-id="currentNode ? currentNode.nodeId : ''"
      :style="hoverPosition"
      @mouseover="stationIn = true"
      @leave="cableTabLeave"
    />
    <associated-segment
      ref="associatedSegment"
      :visible="associatedSegmentVisible"
      :current-edge="currentEdge"
      @close="showAssociatedSegment(false)"
    />
    <IconLIstVue
      :full-screen="fullScreen"
      :icons-visible.sync="iconsVisible"
      :statics-item="staticsItem"
    />
    <div v-show="fullScreen">
      <!-- 开通时，在左侧展示的内容详情 -->
      <open-recommend
        v-if="operateType === 'open'"
        ref="openRecommend"
        :form-data="formData"
        @close="closeBiz"
        @mouseEvent="mouseEventChange"
      />
      <!-- 恢复时，在左侧展示的内容详情 -->
      <restore-recommend
        v-if="operateType === 'restore'"
        ref="restoreRecommend"
        :biz-data="bizData"
        @close="closeBiz"
        @mouseEvent="mouseEventChange"
      />
      <!-- 还原时，在左侧展示的内容详情 -->
      <reduction-recommend
        v-if="operateType === 'reduction'"
        ref="reductionRecommend"
        :biz-data="bizData"
        @close="closeBiz"
        @mouseEvent="mouseEventChange"
      />
      <!-- 关联业务 -->
      <component
        :is="associatedBusinessShow ? 'BusinessList' : ''"
        ref="BusinessList"
        :dialog-visible.sync="associatedBusinessShow"
        :node="currentNode"
      />
      <!-- 故障业务 -->
      <component
        :is="associatedFaultBusinessShow ? 'FaultBusiness' : ''"
        ref="FaultBusiness"
        :dialog-visible.sync="associatedFaultBusinessShow"
        :node="currentNode"
        @restore="restoreFn"
      />
      <!-- 关联路由 -->
      <component
        :is="associatedRouteShow ? 'LinkSegmentList' : ''"
        ref="RouteList"
        :dialog-visible.sync="associatedRouteShow"
        :node="currentNode"
      />
      <!-- 故障路由 -->
      <component
        :is="associatedFaultRouteShow ? 'FaultRoute' : ''"
        ref="FaultRoute"
        :dialog-visible.sync="associatedFaultRouteShow"
        :node="currentNode"
      />
      <!-- 设备拓扑 -->
      <component
        :is="deviceDetailShow ? 'DeviceTopo' : ''"
        ref="deviceTopo"
        :dialog-visible.sync="deviceDetailShow"
        :operate-type="operateType"
        :node="currentNode"
        @selectDevice="selectDevice"
      />
      <!-- 设备端口详情 -->
      <component
        :is="devicePortShow ? 'PortList' : ''"
        ref="PortList"
        :form-data="formData"
        :node="currentDevice"
        :station="currentNode"
        :dialog-visible.sync="devicePortShow"
        :operate-type="operateType"
        @close="closePortList"
      />
      <!-- 光缆端口详情 -->
      <component
        :is="cableDetailShow ? 'CableDetail' : ''"
        ref="CableDetail"
        :node="currentEdge"
        :dialog-visible.sync="cableDetailShow"
      />
      <!-- 新增/修改站点 -->
      <edit-region
        :visible="stationEditShow"
        :type="stationInfo.type"
        :data="stationInfo"
        :function-name="'homeGis'"
        :is-home="true"
        @close="closeArea"
      />
      <component
        :is="associatedBizVisiable ? 'AssociatedBizList' : ''"
        ref="associatedBizList"
        :associated-data="associatedData"
        :visible.sync="associatedBizVisiable"
        @close="associatedBizVisiable = false"
      />

      <facility-editor
        :visible="editFacility"
        :type="currentNode.facilityId ? 'mod' : 'add'"
        :row-data="currentNode"
        @close="closeFacility"
      />
    </div>
  </div>
</template>

<script>
  import { mapGetters, mapMutations } from 'vuex'
  import { intersection } from 'lodash'
  import { deepClone } from '@/utils/common'
  import topoPositionApi from '@/api/oen/TopoPositionApi'
  import homeApi from '@/api/oen/HomeApi'
  import cableSegmentApi from '@/api/oen/CableSegmentApi'
  import regionApi from '@/api/basebiz/RegionApi'
  import nodeApi from '@/api/oen/NodeApi'
  import BizOpenApi from '@/api/oen/BizOpenApi'
  import facilityApi from '@/api/oen/FacilityApi'
  import mixin from './mixin'
  import { formatEdges, formatNodes } from '../vis/js/format'
  // import VisView from '../vis'
  import VisView from '../antv-g6'
  import GisView from '../gis'
  import BusinessList from './components/BusinessList'
  import FaultBusiness from './components/FaultBusiness'
  import LinkSegmentList from './components/LinkSegmentList'
  import DeviceTopo from './components/DeviceTopo'
  import PortList from './components/PortList'
  import CableDetail from './components/CableDetail'
  import OpenRecommend from './components/biz/Open'
  import RestoreRecommend from './components/biz/Restore'
  import ReductionRecommend from './components/biz/Reduction'
  import AddRight from './components/AddRight'
  import CableTabs from './components/CableTabs'
  import StationDetail from './components/StationDetail'
  import EditRegion from '@/views/module/conf/region/Edit'
  import AssociatedSegment from './components/AssociatedSegment'
  import TopFilter from './components/TopFilter'
  import IconLIstVue from './components/IconLIst'
  import AssociatedBizList from './components/AssociatedBizList'
  import facilityEditor from '@/views/module/conf/facility/Edit'
  import GisSearch from './components/GisSearch'
  import LayingMethodFilter from './components/LayingMethodFilter'

  export default {
    name: 'BussinessTopoPage',
    components: {
      VisView,
      GisView,
      BusinessList,
      LinkSegmentList,
      DeviceTopo,
      PortList,
      CableDetail,
      OpenRecommend,
      RestoreRecommend,
      ReductionRecommend,
      FaultBusiness,
      AddRight,
      CableTabs,
      StationDetail,
      EditRegion,
      AssociatedSegment,
      TopFilter,
      IconLIstVue,
      AssociatedBizList,
      facilityEditor,
      GisSearch,
      LayingMethodFilter
    },
    mixins: [mixin],
    props: {
      staticsItem: {
        type: Object,
        default: () => {
          return {
            width: 0,
            height: 0
          }
        }
      },
      previewStatisicsName: {
        type: String,
        default: ''
      }
    },
    provide() {
      return {
        functionName: this.functionName, // 这种注入方式，在拓扑和gis切换时，functionName不会改变
        parentVM: this // 父组件实例
      }
    },
    data() {
      return {
        showLoading: false,
        nodes: [],
        currentDevice: {},
        edges: [],
        operateType: '',
        bizData: null,
        bizNodeList: [],
        bizList: [],
        infoBoxIn: false,
        stationIn: false,
        btnIn: false,
        cableList: [],
        stationEditShow: false,
        stationInfo: {
          type: 'mod'
        },
        associatedSegmentVisible: false,
        formData: {
          aPortData: null,
          zPortData: null,
          aAfsData: null,
          zAfsData: null,
          segmentList: [],
          routeData: null,
          channelData: [],
          actionName: 'open'
        },
        isEdit: false,
        associatedBizVisiable: false,
        zoom: 12,
        editFacility: false,
        showType: 'home',
        associatedData: {},
        rightVisiable: false,
        selectedAll: true// 默认是全选区域
      }
    },
    computed: {
      permission() {
        return this.$store.getters.getAuthData('home:biz')
      },
      ...mapGetters([
        'getTheme',
        'regionStationTree',
        'baseRegionList',
        'mapType',
        'fullScreen',
        'getInfo',
        'stationSelected',
        'ticktack',
        'marqueeList',
        'facilityVisiable',
        'customDictList',
        'getInfo',
        'indexShowRight',
        'oldStationSelected'
      ]),
      dictCableLevelList() {
        return this.customDictList.filter(i => i.type === 'CABLE_LEVEL')
      },
      functionName() {
        return this.mapType === 'VisView' ? 'homeTopo' : 'homeGis'
      }
    },
    watch: {
      ticktack() {
        this.initTopos()
      },
      deviceDetailShow: {
        handler(newVal, oldVal) {
          // 右侧悬浮显示或关闭
          // 存在参数且用户没有主动关闭，就显示右侧悬浮框
          this.$refs.addRight.showRightFn(false)
        }
      },
      cableDetailShow: {
        handler(newVal, oldVal) {
          // 右侧悬浮框显示或关闭
          // 存在参数且用户没有主动关闭，就显示右侧悬浮框
          this.$refs.addRight.showRightFn(false)
        }
      },
      regionStationTree(newVal, oldVal) {
        // 站点新增或修改了
        console.log('更新拓扑')
        this.initTopos()
      },
      marqueeList() {
        if (this.isEdit) return
        this.formateAlarmLevel()
      },
      rightVisiable(newVal, oldVal) {
        if (this.mapType === 'VisView') {
          setTimeout(() => {
            this.$refs.mapContainer.fitView()
          }, 500)
        }
      }
    },
    mounted() {
      this.initTopos()
      this.$nextTick(() => {
        const dom = document.getElementById('mapContainer')
        const myNetworkWrap = dom.parentNode // 画布容器DOM
        this.canvasHeight = myNetworkWrap.offsetHeight
      })
    },
    methods: {
      cableTabsHover(cableId) {
        this.$refs.mapContainer.hoverLine(cableId)
      },
      ...mapMutations(['setGisActived']),
      btnCardIn(data) {
        // console.log('btnCardIn---------', data)
        this.btnIn = data
        if (!data) this.clickProp = ''
      },
      zoomChange(data) {
        this.zoom = data
      },
      initTopos() {
        this.$debounce(this.getTopos)// 会更新拓扑，左侧区域树，与下拉筛选
      },
      getTopos() {
        this.cableList = []
        this.currentNode = {}
        this.currentEdge = {}
        topoPositionApi
          .getTopos()
          .then(res => {
            if (res && res.nodes) {
              this.nodes = formatNodes(res.nodes)
            } else {
              this.nodes = []
            }
            if (res && res.edges) {
              this.edges = formatEdges(res.edges)
            } else {
              this.edges = []
            }
            this.showLoading && this.$message.success(this.$t('DATA_REFRESH_SUCCEEDED'))
            this.showLoading = false
            // 找出每个站点都过哪些光缆
            const newSelectedIds = []
            this.nodes.forEach(i => {
              newSelectedIds.push(i.nodeId)
              const cableLevelList = []
              const cableIdList = []
              this.edges.forEach(j => {
                if (j.fromNodeId === i.nodeId || j.toNodeId === i.nodeId) {
                  cableLevelList.push(j.cableLevel)
                  cableIdList.push(j.cableId)
                }
              })
              i.cableLevelList = Array.from(new Set(cableLevelList))
              i.cableIdList = Array.from(new Set(cableIdList))
              // 如果站点包含有多个光缆等级，则选择最上面的定为该站点的等级
              const statusIndex = i.cableLevelList.map(z =>
                this.dictCableLevelList.findIndex(j => j.code === z)
              )
              const cableLevelIndex = statusIndex.length ? Math.min(...statusIndex) : -1
              i.cableLevel = this.dictCableLevelList[cableLevelIndex]
              i.cableLevelIndex = cableLevelIndex
              if (!i.cableLevel) {
                i.cableLevel = { code: '' }
              }
            })
            this.formateAlarmLevel()
          })
          .catch(err => {
            console.log(err)
          })
      },
      // 站点挂载已有的告警等级
      formateAlarmLevel() {
        const alarmData = {}
        this.marqueeList.forEach(i => {
          if (i.regionId && alarmData[i.regionId]) {
            alarmData[i.regionId].push(i.alarmLevel)
          } else {
            alarmData[i.regionId] = [i.alarmLevel]
          }
        })
        // console.log('alarmData', alarmData)
        this.nodes.forEach(i => {
          if (alarmData[i.nodeId]) {
            i.alarmLevel = Array.from(new Set([...i.alarmLevel, ...alarmData[i.nodeId]]))
          }
        })
        // console.log('this.nodes', this.nodes)
      },
      regionChanged(data) {
        this.selectedAll = data.selectedAll
        if (data.filterType === 'CABLE' && !data.selectedAll) {
          const checkedRegions = []
          this.nodes.forEach(i => {
            if (intersection(i.cableLevelList, data.showRegionIds).length) {
              checkedRegions.push({
                ...i,
                regionId: i.nodeId
              })
            }
          })
          this.$emit('regionChanged', {
            checkedNodes: checkedRegions,
            showRegionIds: checkedRegions.map(i => i.nodeId),
            checkedStation: checkedRegions.map(i => i.nodeId),
            stationSelected: true,
            selectedAll: false,
            filterType: 'CABLE'
          })
        } else {
          this.$emit('regionChanged', data)
        }
      },
      restoreFn(data) {
        // 智能恢复
        console.log(data)
        this.clickProp = ''
        this.bizData = data.bizData
        this.bizData.actionName = data.operateType // 操作日志需要传此类型，判断是开通还是恢复前执行的otdr测试
        this.operateType = data.operateType
      },
      reductionFn(data) {
        console.log(data)
        // 还原
        this.clickProp = ''
        this.bizData = data
        this.operateType = data.operateType
      },
      // 拖拽隐藏弹窗
      dragStart() {
        this.clickProp = ''
      },
      // 业务开通点击
      openClick() {
        this.operateFullScreen()
        this.operateType = 'open'
        this.deviceDetailShow = true
      },
      selectDevice(obj) {
        this.clickProp = ''
        this.currentDevice = obj
        if (obj.mouseStatus === 'SELECT') {
          this.clickProp = 'selectNode'
          this.mouseEvent = 'deviceClick'
          this.calculateSpot(obj, 'click', '.mouseEventClick')
        }
      },
      showPortDetail() {
        this.clickProp = ''
        this.mouseEvent = ''
        this.btnIn = false
        this.devicePortShow = true
      },
      showAssociatedSegment(data) {
        this.operateFullScreen()
        this.associatedSegmentVisible = data
      },
      showAssociatedBiz(type) {
        this.operateFullScreen()
        this.clickProp = ''
        this.mouseEvent = ''
        this.btnIn = false
        this.isEdit = false
        this.infoBoxIn = false
        this.stationIn = false
        if (type === 'cable') {
          this.associatedData = {
            associatedType: type,
            ...this.currentEdge
          }
        } else {
          this.associatedData = {
            associatedType: type,
            ...this.currentDevice
          }
        }
        this.associatedBizVisiable = true
      },
      refreshTopo(showLoading = false) {
        this.showLoading = showLoading
        this.cancelEdit(!showLoading)
        this.formData = this.$options.data().formData
        this.bizData = null
        this.currentNode = {}
        this.currentEdge = {}
        console.log('this.currentNode', this.currentNode)
        this.operateType = ''
        // 重置右侧关联业务弹出框
        this.$refs.addRight.$refs.BizList.reset()
        this.$refs.addRight.$refs.LinkList.reset()
        this.$store.dispatch('getCustomDict')
        this.$store.dispatch('getRegions')
        // this.getTopos()
      },
      cancelEdit(needFitView = true) {
        this.$store.commit('setNeedFitView', needFitView)
        this.oldStationSelected.length &&
          this.$store.commit('setStationSelected', [...this.oldStationSelected])
        this.$store.commit('setOldStationSelected', [])
        this.isEdit = false
        this.infoBoxIn = false
        this.stationIn = false
        this.btnIn = false
        this.currentEdge = {}
        this.showType = 'home'
        this.clickProp = ''
        this.eventName = ''
        this.mouseEvent = ''
        if (this.mapType === 'GisView') {
          this.$refs.mapContainer.removeModifyLine()
          this.$refs.mapContainer.clearDrag(true)
          this.$refs.mapContainer.getInfos()
        } else if (this.mapType === 'VisView') {
          this.$refs.mapContainer.cancelEdit()
        }
      },
      saveEdit() {
        if (this.mapType === 'VisView') {
          this.saveTopos()
        } else if (this.showType === 'cableEidt') {
          this.saveCablePath()
        } else {
          this.saveGisLocation()
        }
      },
      saveGisLocation() {
        const locationData = Object.values(this.$refs.mapContainer.locationChangeData)
        if (locationData.length === 0) {
          this.$message.error(this.$t('NO_DATA_CHANGES'))
          return
        }
        console.log('locationData', locationData)
        const facilities = []
        const regions = []
        locationData.forEach(i => {
          if (i.facilityId) {
            facilities.push({
              facilityId: i.facilityId,
              longitude: i.longitude,
              latitude: i.latitude
            })
          } else {
            regions.push({
              regionId: i.nodeId,
              longitude: i.longitude,
              latitude: i.latitude
            })
          }
        })
        homeApi
          .saveBatchLocation({
            facilities,
            regions
          })
          .then(res => {
            if (!res) {
              this.$message.success(this.$t('SAVEFAILED'))
              return
            }
            this.$message.success(this.$t('SAVE_SUCCESS'))
            this.isEdit = false
            this.$refs.mapContainer.clearDrag(true)
            const regionChanged = !!regions.length
            const facilityChanged = !!facilities.length
            regionChanged && this.$store.commit('changeTicktack')
            facilityChanged && this.$refs.mapContainer.getInfos(!regionChanged)
            this.$store.commit('setNeedFitView', false)
            if (regionChanged) {
              this.$store.dispatch('getRegions', { orgId: this.getInfo.org.orgId })
            }
          }).catch(err => {
            console.log(err)
          })
      },
      saveTopos() {
        // const topoPositions = this.$refs.mapContainer.myNetwork.getPositions() || {}
        const topoPositions = this.$refs.mapContainer.graph.save() || {}
        const nodeList = topoPositions.nodes.map((ele, index) => {
          return {
            type: 'STATION',
            nodeId: ele.nodeId,
            x: ele.x,
            y: ele.y
          }
        })
        topoPositionApi
          .savePosition(nodeList)
          .then(res => {
            this.isEdit = false
            this.$message.success(this.$t(res ? 'SAVE_SUCCESS' : 'SAVEFAILED'))
            this.getTopos()
          })
          .catch(() => {})
      },
      closeBiz() {
        this.operateType = ''
        this.formData = this.$options.data().formData
        this.bizData = null
      },
      mouseEventChange(data) {
        console.log('触发了')
        this.$refs.mapContainer.hoverEdges(data)
      },
      // 查询站点下的业务设备
      async getNodeList(stationId) {
        this.bizNodeList = []
        await nodeApi.queryList({ stationIdList: [stationId] }).then(res => {
          // 节点只能选择传输设备和光分
          res = (res || []).filter(
            i => i.nodeCategory === 'TRANSPORT' || i.nodeCategory === 'LIGHT_SPLIT'
          )
          this.bizNodeList = res
        }).catch(err => {
          console.log(err)
        })
      },
      // 查询站点下的故障业务
      async getBizList(stationId) {
        await BizOpenApi.queryList({ stationId: [stationId], bizStatus: 'FAULT' }).then(res => {
          if (res && res.length) {
            res.sort((a, b) => {
              return b.createTime < a.createTime ? -1 : 1
            })
          }
          this.bizList = res || []
        }).catch(err => {
          console.log(err)
        })
      },
      changeMap() {
        if (this.mapType === 'GisView' && this.selectedAll) {
          const mapBox = this.$refs.mapContainer
          const zoom = mapBox.map.getView().getZoom() // 获取当前地图的缩放级别
          const center = mapBox.map.getView().getCenter()
          this.$store.commit('setCurZoomView', { zoom, center })
        }
        this.$store.commit('setMapType', this.mapType === 'GisView' ? 'VisView' : 'GisView')
        setTimeout(() => {
          this.$refs.mapContainer.fitView(this.stationSelected)
        }, 500)
      },
      locatePoint(center) {
        this.$refs.mapContainer.setCenter(center)
      },
      editStation() {
        const regionData = this.baseRegionList.find(i => i.regionId === this.currentNode.nodeId)
        this.stationInfo = {
          ...regionData,
          type: 'mod'
        }
        this.stationEditShow = true
        this.operateFullScreen()
      },
      addStation() {
        // console.log('this.stationSelected', this.stationSelected)
        this.$store.commit('setFullScreen', true)
        this.stationInfo = {
          type: 'add',
          parentId: '',
          operateType: 'GIS',
          regionType: 'STATION',
          virtualFlag: false,
          longitude: this.currentNode.longitude,
          latitude: this.currentNode.latitude
        }
        this.stationEditShow = true
      },
      closeArea(stationInfo) {
        this.stationEditShow = false
        if (stationInfo.load === true) {
          this.$store.commit('setNeedFitView', false)
          this.$store.dispatch('getRegions', { orgId: this.getInfo.org.orgId }) // 通知全局站点被修改或新增
          const ids = [...this.stationSelected, stationInfo.regionId]
          this.$store.commit('setStationSelected', ids)
          this.$store.commit('setFilterStationIds', ids)
          // 更新站点，光缆，光缆段里的经纬度
          // this.$refs.businessGis.addOrModStation(stationInfo)
        }
        this.stationInfo = { type: 'mod' }
        this.clickProp = ''
        this.mouseEvent = ''
      },
      closePortList(data) {
        this.devicePortShow = false
        data.closeDevice && (this.deviceDetailShow = false)
      },
      locateAlarm(data, includeNode = false) {
        if (data.isAlarm) {
          this.$refs.TopFilter.clear()
        }
        const alarmStation = this.nodes.find(i => i.nodeId === data.regionId)
        if (!alarmStation) {
          this.$message.warning(
            this.$t('NONE_STATION_BELONE_ALARM', { msg: data.device ? data.device.deviceName : '' })
          )
          return
        }
        if (!includeNode) {
          const ids = this.nodes.map(i => i.nodeId)
          this.$store.commit('setStationSelected', ids)
          this.$store.commit('setFilterStationIds', ids)
        }
        this.setGisActived({
          cableIds: [],
          nodeIds: alarmStation.nodeId ? [alarmStation.nodeId] : [],
          color: 'highLight'
        })
      },
      addFacility() {
        // console.log('addFacility')
        this.$store.commit('setFullScreen', true)
        this.editFacility = true
        // this.$refs.mapContainer.nodeDragged()
      },
      closeFacility(data) {
        this.clickProp = ''
        this.eventName = ''
        this.mouseEvent = ''
        this.editFacility = false
        if (data === 'load') {
          this.$refs.mapContainer.getInfos()
        }
      },
      delFacility() {
        this.clickProp = ''
        this.eventName = ''
        this.$confirm(
          this.$t('CONFIRM_DELETION_PROMPT_TIP', {
            key: this.$t('GEO_NODE'),
            value: this.currentNode.facilityName
          }),
          { type: 'warning' }
        )
          .then(() => {
            facilityApi
              .del(
                { id: this.currentNode.id, facilityName: this.currentNode.facilityName, functionName: 'homeGis' } // 操作日志需要此参数
              )
              .then(res => {
                if (res) {
                  this.$message.success(this.$t('DELETE_SUCCESS'))
                  this.$refs.mapContainer.getInfos()
                } else {
                  this.$message.success(this.$t('DELETEFAILED'))
                }
              })
              .catch(() => {})
          })
          .catch(() => {})
      },
      async delStation() {
        this.clickProp = ''
        this.eventName = ''
        const stationData = this.currentNode
        // console.log('delStation', stationData)
        const res = await nodeApi.getByRegionIds({ regionIds: [stationData.nodeId] })
        if (res && res[stationData.nodeId]) {
          const nodes = res[stationData.nodeId].map(item => item.nodeName).join(',')
          this.$alert(
            this.$t('CANNOT_DEL_STATION_OR_ROOM_ALERT', {
              station: stationData.label,
              nodes: nodes
            }),
            this.$t('DEL'),
            {
              confirmButtonText: this.$t('YES'),
              type: 'warning',
              callback: action => {}
            }
          )
          return
        }
        this.$confirm(
          this.$t('CONFIRM_DELETE_THIS', {
            type: this.$t('REGION_TYPE_STATION'),
            name: stationData.label
          }),
          { type: 'warning' }
        )
          .then(() => {
            regionApi
              .delByRegionId(
                { regionId: stationData.nodeId,
                  logParams: { regionName: stationData.label, regionType: 'STATION' }
                }
              )
              .then(res => {
                if (res) {
                  this.$message.success(this.$t('DELETE_SUCCESS'))
                  this.getTopos()
                }
              }).catch(err => {
                console.log(err)
              })
          })
          .catch(() => {})
      },
      modMap() {
        this.isEdit = true
        this.$store.commit('setFullScreen', true)
        this.$store.commit('showFacility', true)
        if (this.mapType === 'GisView') {
          this.$refs.mapContainer.modlocation()
        }
      },
      autoLayout() {
        if (this.mapType === 'VisView') {
          this.$refs.mapContainer.autoLayout()
        }
      },
      editPath() {
        // console.log('this.edges', this.edges)
        this.$store.commit('setOldStationSelected', [...this.stationSelected])
        this.isEdit = true
        this.showType = 'cableEidt'
        this.clickProp = ''
        this.eventName = ''
        this.$store.commit('setFullScreen', true)
        this.$store.commit('showFacility', true)
        const edgeData = deepClone(this.currentEdge)
        const nodeList = [edgeData.fromNodeId, edgeData.toNodeId]
        this.$store.commit('setStationSelected', nodeList)
        this.$store.commit('setGisActived', {
          cableIds: [edgeData.cableId],
          nodeIds: nodeList,
          color: 'normal'
        })
        setTimeout(() => {
          this.$refs.mapContainer.drawLine(edgeData)
        })
      },
      saveCablePath() {
        const params = this.$refs.mapContainer.getLineData()
        cableSegmentApi
          .modify({ ...params, logParams: { actionName: 'editPath', functionName: this.functionName }})
          .then(res => {
            if (res) {
              this.cancelEdit(false)
              this.$message.success(this.$t('SAVE_SUCCESS') + this.$t('UPDATE_CABLE_SEGMENT'))
            } else {
              this.$message.success(this.$t('SAVEFAILED'))
            }
          })
          .catch(() => {})
      },
      rightVisiableChange(data) {
        this.rightVisiable = data
      }
    }
  }
</script>
<style lang="scss" scoped>
  @import '@/assets/css/mixin.module.scss';
  .map-top {
    height: 28px;
    min-height: 28px;
    position: absolute;
    top: 5px;
    left: 0;
    right: 0;
    margin: 0 auto;
    z-index: 1;
    transition: all 0.5s;
  }
  .topo-wrap {
    // position: relative;
    ::v-deep .el-card__body {
      padding: 5px;
    }
    ::v-deep .el-collapse {
      &-item__header {
        background-color: rgba(0, 0, 0, 0);
      }
      &-item__wrap {
        background-color: rgba(0, 0, 0, 0);
      }
      &-item__content {
        padding-bottom: 0;
      }
    }
    .mouseEventClick{
      opacity: 0;
      &.opacity1{
        opacity: 1;
      }
    }
    .edges-tooltip {
      position: absolute;

      li + li {
        margin-top: 5px;
      }
    }
    ::v-deep .open-box {
      position: absolute;
      top: 50px;
      left: 10px;
      width: 400px;
      z-index: 10;
      height: calc(100% - 60px);
      padding-bottom: 5px;
      @include themeify {
        border: 1px solid themed('homeBorderColor');
        background: rgba($color: themed('homeBoxBgColor'), $alpha: 0.7);
      }

      label,
      p {
        @include themeify {
          color: themed('textColor');
        }
        font-size: 14px;
        line-height: 20px;
      }

      .test-progress {
        color: #1c1b1b;
      }
    }
    .cable-name {
      margin-bottom: 5px;
      max-width: 200px;
      font-weight: bold;
      word-break: break-all;
    }
  }
</style>
./mixin
